package fem2.pre_and_post;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Scanner;

import fem2.MeshGenerator;

public class GmshMeshGenerator extends MeshGenerator {

	private static final String ELEMENT_HEADER_START = "$Elements";
	private static final String ELEMENT_HEADER_END = "$EndElements";
	private static final String COORDINATES_HEADER_START = "$Nodes";
	private static final String COORDINATES_HEADER_END = "$EndNodes";
	private static final int ELEMENT_BASE_INDEX = 1;

	private File file;

	public GmshMeshGenerator(String fileName) {
		file = new File(fileName);
	}

	@Override
	public ArrayList<double[]> getNodes(int dim) {
		ArrayList<double[]> nodes = new ArrayList<double[]>();
		Scanner scanner = null;
		try {
			scanner = new Scanner(new FileReader(file));
		} catch (FileNotFoundException e) {
			throw new Error("File not found");
		}
		try {
			boolean startRead = false;
			// use a Scanner to get each line
			while (scanner.hasNextLine()) {
				String line = scanner.nextLine();
				if (line.compareTo(COORDINATES_HEADER_START) == 0) {
					startRead = true;
					scanner.nextLine();// skip the number of nodes
					continue;
				} else if (line.compareTo(COORDINATES_HEADER_END) == 0)
					break;
				if (startRead) {
					Scanner lineScanner = new Scanner(line);
					if (lineScanner.hasNext()) {
						double[] v;
						lineScanner.next(); // skip the index
						double x = Double.parseDouble(lineScanner.next());
						double y = Double.parseDouble(lineScanner.next());
						if (dim == 2) {
							v = new double[] { x, y };
						} else if (dim == 3) {
							double z = Double.parseDouble(lineScanner.next());
							v = new double[] { x, y, z };
						} else {
							lineScanner.close();
							throw new Error("invalid dimension");
						}
						nodes.add(v);
					} else {
						lineScanner.close();
						throw new Error("Empty or invalid line. Unable to process.");
					}
					lineScanner.close();
				}
			}
		} finally {
			scanner.close();
		}
		return nodes;
	}

	@Override
	public ArrayList<ArrayList<Integer>> getConnectivities() {
		ArrayList<ArrayList<Integer>> elements = new ArrayList<ArrayList<Integer>>();
		Scanner scanner = null;
		try {
			scanner = new Scanner(new FileReader(file));
		} catch (FileNotFoundException e1) {
			throw new Error("File not fouble");
		}
		try {
			boolean startRead = false;
			// use a Scanner to get each line
			while (scanner.hasNextLine()) {
				String line = scanner.nextLine();
				if (line.compareTo(ELEMENT_HEADER_START) == 0) {
					startRead = true;
					scanner.nextLine();// skip the number of elements
					continue;
				} else if (line.compareTo(ELEMENT_HEADER_END) == 0)
					break;
				if (startRead) {
					Scanner lineScanner = new Scanner(line);
					if (lineScanner.hasNext()) {
						lineScanner.next(); // skip the index
						lineScanner.next(); // skip the element type
						lineScanner.next(); //
						lineScanner.next(); //
						lineScanner.next(); //
						ArrayList<Integer> e = new ArrayList<Integer>();
						while (lineScanner.hasNext())
							e.add(Integer.parseInt(lineScanner.next()) - ELEMENT_BASE_INDEX);
						elements.add(e);
					} else {
						lineScanner.close();
						throw new Error("Empty or invalid line. Unable to process.");
					}
					lineScanner.close();
				}
			}
		} finally {
			scanner.close();
		}
		return elements;
	}

}
